﻿using System.Linq;
using System.Threading;
using Citi.SecurityHelper;
using System.Threading.Tasks;
using SHDocVw;
using Citi.SecurityWebBrowser;
using System.Runtime.InteropServices;
using System.Runtime.InteropServices.ComTypes;
using System;
using System.Text.RegularExpressions;
using System.Collections;
using System.Text;
using System.Runtime.CompilerServices;

namespace System.Windows.Forms
{
    public static class SingleSignOn
    {
        private static string originalUrl;
        private static string Soeid;
        private static Citi.SecurityHelper.LoginType LoginType;
        private static bool urlChanged;
        private static bool logged;
        private static WebBrowser browser;

        public static void browser_DocumentCompleted(object sender, WebBrowserDocumentCompletedEventArgs e)
        {
            if (!urlChanged)
            {
                return;
            }

            var webBrowser = (WebBrowser)sender;

            webBrowser.Navigated -= webBrowser_Navigated;
            LogUser(webBrowser);
        }

        public static void browser_DocumentCompletedUserLogged(object sender, WebBrowserDocumentCompletedEventArgs e)
        {
            logged = true;
        }

        public static void LogSingleSignOn(this WebBrowser webBrowser, string soeid, Citi.SecurityHelper.LoginType loginType, string url = null)
        {
            originalUrl = originalUrl ?? url;
            Soeid = soeid;
            LoginType = loginType;
            logged = false;

            //var axbrowser = (SHDocVw.WebBrowser_V1)webBrowser.ActiveXInstance;
            //axbrowser.NewWindow += webBrowser_NewWindow;
            browser = webBrowser;

            if (!string.IsNullOrWhiteSpace(url))
                webBrowser.Navigate(url);

            webBrowser.DocumentCompleted += browser_DocumentCompleted;

            while (webBrowser.ReadyState != WebBrowserReadyState.Complete)
            {
                Application.DoEvents();
                Thread.Sleep(100);
            }

            LogUser(webBrowser);
        }

        private static void LogUser(WebBrowser webBrowser)
        {
            var password = CitiEncryption.GetDecryptedPassword(Soeid, LoginType, SecurityConfigurations.RobotUserName, SecurityConfigurations.RobotPassword);

            HtmlElementCollection form = webBrowser.Document.GetElementsByTagName("form");
            HtmlElement textName = webBrowser.Document.GetElementById("USER");

            if (textName == null)
            {
                webBrowser.Navigated += webBrowser_Navigated;
                return;
            }

            textName.SetAttribute("value", Soeid);
            HtmlElement textPassword = webBrowser.Document.GetElementById("PASSWORD");
            textPassword.SetAttribute("value", password);

            var inputs = form[0].GetElementsByTagName("input").Cast<HtmlElement>();

            var button = inputs.FirstOrDefault(x => !string.IsNullOrWhiteSpace(x.OuterHtml) && x.OuterHtml.Contains("button"));

            browser.DocumentCompleted -= browser_DocumentCompleted;
            browser.DocumentCompleted += browser_DocumentCompletedUserLogged;

            button.InvokeMember("Click");

            //while (webBrowser.ReadyState != WebBrowserReadyState.Complete)
            while (!logged)
            {
                Application.DoEvents();
                Thread.Sleep(100);
            }
        }

        static void webBrowser_Navigated(object sender, WebBrowserNavigatedEventArgs e)
        {
            urlChanged = originalUrl != e.Url.OriginalString;
        }

        private static void webBrowser_NewWindow(string url, int glags, string targetFrameName, ref object postData, string headers, ref bool processed)
        {
            processed = true;
            browser.Navigate(url);
        }

        static bool navigateFinished;

        public static void WaitNavigate(this WebBrowser webBrowser, string url)
        {
            navigateFinished = false;
            webBrowser.DocumentCompleted += browser_DocumentCompletedNavigation;
            webBrowser.Navigate(url);

            while (!navigateFinished)
            {
                Application.DoEvents();
                Thread.Sleep(100);
            }

            //var tokenSource = new CancellationTokenSource();
            //var token = tokenSource.Token;
            //var timeOut = 60000;

            // var task = Task.Factory.StartNew(() => WaitNavigate(browser), token);

            // if (!task.Wait(timeOut, token))
            // {
            //     throw new TimeoutException();
            // }

            //webBrowser.DocumentCompleted -= browser_DocumentCompletedNavigation;
            //var wait = new Thread(WaitNavigate, );

            //while(!navigateFinished)
            //{
            //    Thread.Sleep(100);
            //}
        }

        public static void browser_DocumentCompletedNavigation(object sender, WebBrowserDocumentCompletedEventArgs e)
        {
            navigateFinished = true;
        }

        private static void WaitNavigate(WebBrowser webBrowser)
        {
            while (!navigateFinished)
            {
                Thread.Sleep(100);
            }
        }

        public static bool AllElementExist(this WebBrowser webBrowser, string elementString)
        {
            var elements = elementString.Split('.');
            var javascriptExecuted = string.Empty;

            foreach (var element in elements)
            {
                if (!string.IsNullOrEmpty(javascriptExecuted))
                    javascriptExecuted += ".";

                javascriptExecuted += element;

                var exists = ElementExists(webBrowser, javascriptExecuted);

                if (!exists) return false;
            }

            return true;
        }

        public static bool ElementExists(this WebBrowser webBrowser, string elementString)
        {
            try
            {
                return (bool)webBrowser.Document.InvokeScript("eval", new[] { string.Format("{0} != undefined", elementString) });
            }
            catch
            {
                return false;
            }
        }

        public static bool WaitUntilExist(this WebBrowser webBrowser, string elementString, int timeout = 60000, bool throwOnTimeout = true)
        {
            var elementsExist = webBrowser.AllElementExist(elementString);
            var startDate = DateTime.Now;

            while (!elementsExist)
            {
                Application.DoEvents();
                Thread.Sleep(100);
                elementsExist = webBrowser.AllElementExist(elementString);

                if ((startDate - DateTime.Now).TotalMilliseconds > timeout)
                {
                    if (throwOnTimeout)
                        throw new Exception(string.Format("Timeout expired. Could not find '{0}'", elementsExist));

                    return false;
                }
            }

            return true;
        }
    }
}

[ComVisible(true)]
public class BrowserRemotingProxy : MarshalByRefObject, IAuthenticate,
IServiceProvider
{
    public Guid IID_IProfferService = new Guid("cb728b20-f786-11ce-92ad-00aa00a74cd0");
    public Guid SID_SProfferService = new Guid("cb728b20-f786-11ce-92ad-00aa00a74cd0");
    public Guid IID_IAuthenticate = new Guid("79eac9d0-baf9-11ce-8c82-00aa004ba90b");

    public BrowserRemotingProxy(System.Windows.Forms.WebBrowser browserControl)
    {
        this.browserControl = browserControl;
        //this.IE = browserControl.ActiveXInstance as InternetExplorer;
        this.IE = (SHDocVw.InternetExplorer)browserControl.ActiveXInstance;
        IServiceProvider sp = this.IE as IServiceProvider;
        IProfferService theProfferService = null;
        IntPtr objectProffer = IntPtr.Zero;
        uint cookie = 0;
        sp.QueryService(ref SID_SProfferService, ref IID_IProfferService, out objectProffer);
        theProfferService = Marshal.GetObjectForIUnknown(objectProffer) as IProfferService;
        theProfferService.ProfferService(ref IID_IAuthenticate, this, out cookie);
    }
    #region IServiceProvider Members

    void IServiceProvider.QueryService(ref Guid guidService, ref Guid riid, out IntPtr ppvObject)
    {
        //int hr = HRESULT.E_NOINTERFACE;

        if (guidService == IID_IAuthenticate && riid == IID_IAuthenticate)
        {
            ppvObject = Marshal.GetComInterfaceForObject(this, typeof(IAuthenticate)); // this as IAuthenticate; // 
            //if (ppvObject != null) {
            //    hr = HRESULT.S_OK;
            //}
        }
        else
        {
            ppvObject = IntPtr.Zero;
        }
        //return hr;
    }

    #endregion

    #region IAuthenticate Members

    void IAuthenticate.Authenticate(out IntPtr phwnd, out string pszUsername, out string pszPassword)
    {
        phwnd = IntPtr.Zero;
        pszUsername = "e6osnaa";
        pszPassword = "trbg33";
    }
    #endregion

    private System.Windows.Forms.WebBrowser browserControl;
    private InternetExplorer IE;
}
#region COM Interfaces import Declarations
public struct HRESULT
{
    public const int S_OK = 0;
    public const int S_FALSE = 1;
    public const int E_NOTIMPL = unchecked((int)0x80004001);
    public const int E_INVALIDARG = unchecked((int)0x80070057);
    public const int E_NOINTERFACE = unchecked((int)0x80004002);
    public const int E_FAIL = unchecked((int)0x80004005);
    public const int E_UNEXPECTED = unchecked((int)0x8000FFFF);
}
#region IServiceProvider Interface

[ComImport, InterfaceType(ComInterfaceType.InterfaceIsIUnknown),
 Guid("6D5140C1-7436-11CE-8034-00AA006009FA")]
public interface IServiceProvider
{
    [MethodImpl(MethodImplOptions.InternalCall, MethodCodeType = MethodCodeType.Runtime)]
    void QueryService([In] ref Guid guidService, [In] ref Guid riid, [Out] out IntPtr ppvObject);
}

#endregion
#region IProfferService Interface
[ComImport, InterfaceType(ComInterfaceType.InterfaceIsIUnknown),
 Guid("CB728B20-F786-11CE-92AD-00AA00A74CD0")]
public interface IProfferService
{
    [MethodImpl(MethodImplOptions.InternalCall, MethodCodeType =
MethodCodeType.Runtime)]
    void ProfferService([In] ref Guid rguidService, [In,
MarshalAs(UnmanagedType.Interface)] IServiceProvider psp, out uint pdwCookie);
    [MethodImpl(MethodImplOptions.InternalCall, MethodCodeType =
MethodCodeType.Runtime)]
    void RevokeService([In] uint dwCookie);
}

#endregion
#region IAuthenticate Interface
//MIDL_INTERFACE("79eac9d0-baf9-11ce-8c82-00aa004ba90b")
//IAuthenticate : public IUnknown
//{
//public:
//    virtual HRESULT STDMETHODCALLTYPE Authenticate( 
//        /* [out] */ HWND *phwnd,
//        /* [out] */ LPWSTR *pszUsername,
//        /* [out] */ LPWSTR *pszPassword) = 0;
//}
[ComImport, InterfaceType(ComInterfaceType.InterfaceIsIUnknown),
ComConversionLoss, Guid("79EAC9D0-BAF9-11CE-8C82-00AA004BA90B")]
public interface IAuthenticate
{
    [MethodImpl(MethodImplOptions.InternalCall, MethodCodeType = MethodCodeType.Runtime)]
    void Authenticate([Out, ComAliasName("UrlMonInterop.wireHWND")] out IntPtr phwnd, [Out, MarshalAs(UnmanagedType.LPWStr)] out string pszUsername,
        [Out, MarshalAs(UnmanagedType.LPWStr)] out string pszPassword);
}
#endregion
#endregion

//#region IDownloadManager Interface
////MIDL_INTERFACE("988934A4-064B-11D3-BB80-00104B35E7F9")
////IDownloadManager : public IUnknown
////{
////public:
////    virtual HRESULT STDMETHODCALLTYPE Download( 
////        /* [in] */ IMoniker *pmk,
////        /* [in] */ IBindCtx *pbc,
////        /* [in] */ DWORD dwBindVerb,
////        /* [in] */ LONG grfBINDF,
////        /* [in] */ BINDINFO *pBindInfo,
////        /* [in] */ LPCOLESTR pszHeaders,
////        /* [in] */ LPCOLESTR pszRedir,
////        /* [in] */ UINT uiCP) = 0;
////}
//[ComVisible(true), ComImport]
//[Guid("988934A4-064B-11D3-BB80-00104B35E7F9")]
//[InterfaceType(ComInterfaceType.InterfaceIsIUnknown)]
//public interface IDownloadManager
//{
//    [return: MarshalAs(UnmanagedType.I4)]
//    [PreserveSig]
//    int Download(
//        [In, MarshalAs(UnmanagedType.Interface)] IMoniker pmk,
//        [In, MarshalAs(UnmanagedType.Interface)] IBindCtx pbc,
//        [In, MarshalAs(UnmanagedType.U4)] UInt32 dwBindVerb,
//        [In] int grfBINDF,
//        [In, MarshalAs(UnmanagedType.Struct)] ref BINDINFO pBindInfo,
//        [In, MarshalAs(UnmanagedType.LPWStr)] string pszHeaders,
//        [In, MarshalAs(UnmanagedType.LPWStr)] string pszRedir,
//        [In, MarshalAs(UnmanagedType.U4)] uint uiCP);
//}
//#endregion

//#region IServiceProvider Interface
////MIDL_INTERFACE("6d5140c1-7436-11ce-8034-00aa006009fa")
////IServiceProvider : public IUnknown
////{
////public:
////    virtual /* [local] */ HRESULT STDMETHODCALLTYPE QueryService( 
////        /* [in] */ REFGUID guidService,
////        /* [in] */ REFIID riid,
////        /* [out] */ void __RPC_FAR *__RPC_FAR *ppvObject) = 0;

////    template <class Q>
////    HRESULT STDMETHODCALLTYPE QueryService(REFGUID guidService, Q** pp)
////    {
////        return QueryService(guidService, __uuidof(Q), (void **)pp);
////    }
////};
//[ComImport, ComVisible(true)]
//[Guid("6d5140c1-7436-11ce-8034-00aa006009fa")]
//[InterfaceType(ComInterfaceType.InterfaceIsIUnknown)]
//public interface IServiceProvider
//{
//    [return: MarshalAs(UnmanagedType.I4)]
//    [PreserveSig]
//    int QueryService(
//        [In] ref Guid guidService,
//        [In] ref Guid riid,
//        [Out] out IntPtr ppvObject);
//    //This does not work i.e.-> ppvObject = (INewWindowManager)this
//    //[Out, MarshalAs(UnmanagedType.Interface)] out object ppvObject);
//}
//#endregion

//[StructLayout(LayoutKind.Sequential)]
//public struct BINDINFO
//{
//    [MarshalAs(UnmanagedType.U4)]
//    public uint cbSize;
//    [MarshalAs(UnmanagedType.LPWStr)]
//    public string szExtraInfo;
//    [MarshalAs(UnmanagedType.Struct)]
//    public STGMEDIUM stgmedData;
//    [MarshalAs(UnmanagedType.U4)]
//    public uint grfBindInfoF;
//    [MarshalAs(UnmanagedType.U4)]
//    public uint dwBindVerb;
//    [MarshalAs(UnmanagedType.LPWStr)]
//    public string szCustomVerb;
//    [MarshalAs(UnmanagedType.U4)]
//    public uint cbstgmedData;
//    [MarshalAs(UnmanagedType.U4)]
//    public uint dwOptions;
//    [MarshalAs(UnmanagedType.U4)]
//    public uint dwOptionsFlags;
//    [MarshalAs(UnmanagedType.U4)]
//    public uint dwCodePage;
//    [MarshalAs(UnmanagedType.Struct)]
//    public SECURITY_ATTRIBUTES securityAttributes;
//    public Guid iid;
//    [MarshalAs(UnmanagedType.IUnknown)]
//    public object punk;
//    [MarshalAs(UnmanagedType.U4)]
//    public uint dwReserved;
//}

//////typedef struct _REMSECURITY_ATTRIBUTES
//////{
//////DWORD nLength;
//////DWORD lpSecurityDescriptor;
//////BOOL bInheritHandle;
//////} 	REMSECURITY_ATTRIBUTES;
//[StructLayout(LayoutKind.Sequential)]
//public struct SECURITY_ATTRIBUTES
//{
//    [MarshalAs(UnmanagedType.U4)]
//    public uint nLength;
//    public IntPtr lpSecurityDescriptor;
//    [MarshalAs(UnmanagedType.Bool)]
//    public bool bInheritHandle;
//}

///// <summary>
///// Intercepts downloads of files, to add as PDFs or suppliments
///// </summary>
//[ComVisible(true)]
//[Guid("bdb9c34c-d0ca-448e-b497-8de62e709744")]
//[CLSCompliant(false)]
//public class DownloadManager : IDownloadManager
//{
//    [DllImport("ole32.dll")]
//    static extern int CreateBindCtx(uint reserved, out IBindCtx ppbc);

//    public int Download(IMoniker pmk, IBindCtx pbc, uint dwBindVerb, int grfBINDF, ref BINDINFO pBindInfo, string pszHeaders, string pszRedir, uint uiCP)
//    {
//        // Get the display name of the pointer to an IMoniker interface that specifies the object to be downloaded.
//        string name;
//        pmk.GetDisplayName(pbc, null, out name);
//        if (!string.IsNullOrEmpty(name))
//        {
//            Uri url;
//            if (Uri.TryCreate(name, UriKind.Absolute, out url))
//            {
//                //Debug.WriteLine("DownloadManager: initial URL is: " + url);
//                CreateBindCtx(0, out pbc);
//                //RegisterCallback(pbc, url);
//                //BindMonikerToStream(pmk, pbc);

//                return Constants.S_OK;
//            }
//        }
//        return 1;
//    }
//}

//public class DownloadWebBrowserSite : IServiceProvider
//{
//    WebBrowser browser;

//    public DownloadWebBrowserSite(WebBrowser webBrowser)
//    {
//        browser = webBrowser;    
//    }

//    private CSEXWBDLMANLib.IcsDLMan m_csexwbCOMLib = null;

//    public int QueryService(ref Guid guidService, ref Guid riid, out IntPtr ppvObject)
//    {
//        if ((guidService == Constants.IID_IDownloadManager && riid == Constants.IID_IDownloadManager))
//        {
//            ppvObject = Marshal.GetComInterfaceForObject(browser, typeof(IDownloadManager));
//            return Constants.S_OK;
//        }
//        ppvObject = IntPtr.Zero;
//        return Constants.E_NOINTERFACE;

//        //if ((guidService == Constants.IID_IDownloadManager && riid == Constants.IID_IDownloadManager))
//        //{
//        //    AddThisIEServerHwndToComLib();
//        //    //QI for IDownloadManager interface from our COM object
//        //    ppvObject = Marshal.GetComInterfaceForObject(m_csexwbCOMLib, typeof(IDownloadManager));
//        //    return Constants.S_OK;
//        //}
//        //ppvObject = IntPtr.Zero;
//        //return Constants.E_NOINTERFACE;

//    }

//    private bool AddThisIEServerHwndToComLib()
//    {
//        if ((m_csexwbCOMLib.HWNDInternetExplorerServer == 0) &&
//            (WBIEServerHandle() != IntPtr.Zero))
//        {
//            m_csexwbCOMLib.HWNDInternetExplorerServer = m_hWBServerHandle.ToInt32();
//            return true;
//        }
//        else
//            return false;
//    }
//    private IntPtr m_hWBServerHandle = (IntPtr)0;
//    private IntPtr m_hWBShellDocObjHandle = (IntPtr)0;
//    private IntPtr m_hWBShellEmbeddingHandle = (IntPtr)0;
//    private IntPtr m_NullPointer = IntPtr.Zero;

//    private IntPtr WBIEServerHandle()
//    {
//        if ((!m_hWBServerHandle.Equals(m_NullPointer)) &&
//            (WinApis.IsWindow(m_hWBServerHandle)))
//            return m_hWBServerHandle;
//        if (!WBShellDocObjHandle().Equals(m_NullPointer))
//        {
//            m_hWBServerHandle = WinApis.GetWindow(m_hWBShellDocObjHandle, (uint)GetWindow_Cmd.GW_CHILD);
//        }
//        return m_hWBServerHandle;
//    }

//    private IntPtr WBShellDocObjHandle()
//    {
//        if ((!m_hWBShellDocObjHandle.Equals(m_NullPointer)) &&
//            (WinApis.IsWindow(m_hWBShellDocObjHandle)))
//            return m_hWBShellDocObjHandle;
//        m_hWBShellDocObjHandle = m_NullPointer;
//        if (!WBShellEmbedingHandle().Equals(m_NullPointer))
//        {
//            m_hWBShellDocObjHandle = WinApis.GetWindow(m_hWBShellEmbeddingHandle, (uint)GetWindow_Cmd.GW_CHILD);
//        }
//        return m_hWBShellDocObjHandle;
//    }

//    private object m_WBUnknown = null;

//    private IntPtr WBShellEmbedingHandle()
//    {
//        if (m_WBUnknown == null)
//            return m_NullPointer;

//        if ((!m_hWBShellEmbeddingHandle.Equals(m_NullPointer)) &&
//            (WinApis.IsWindow(m_hWBShellEmbeddingHandle)))
//            return m_hWBShellEmbeddingHandle;

//        m_hWBShellEmbeddingHandle = m_NullPointer;

//        IOleWindow pWin = m_WBUnknown as IOleWindow;
//        if (pWin != null)
//            pWin.GetWindow(ref m_hWBShellEmbeddingHandle);

//        return m_hWBShellEmbeddingHandle;
//    }
//}

//public sealed class Constants
//{
//    //SID_STopWindow = {49e1b500-4636-11d3-97f7-00c04f45d0b3}
//    public static Guid IID_IUnknown = new Guid("00000000-0000-0000-C000-000000000046");
//    public static Guid IID_IViewObject = new Guid("0000010d-0000-0000-C000-000000000046");
//    public static Guid IID_IAuthenticate = new Guid("79eac9d0-baf9-11ce-8c82-00aa004ba90b");
//    public static Guid IID_IWindowForBindingUI = new Guid("79eac9d5-bafa-11ce-8c82-00aa004ba90b");
//    public static Guid IID_IHttpSecurity = new Guid("79eac9d7-bafa-11ce-8c82-00aa004ba90b");
//    //SID_SNewWindowManager same as IID_INewWindowManager
//    public static Guid IID_INewWindowManager = new Guid("D2BC4C84-3F72-4a52-A604-7BCBF3982CBB");
//    public static Guid IID_IOleClientSite = new Guid("00000118-0000-0000-C000-000000000046");
//    public static Guid IID_IDispatch = new Guid("{00020400-0000-0000-C000-000000000046}");
//    public static Guid IID_TopLevelBrowser = new Guid("4C96BE40-915C-11CF-99D3-00AA004AE837");
//    public static Guid IID_WebBrowserApp = new Guid("0002DF05-0000-0000-C000-000000000046");
//    public static Guid IID_IBinding = new Guid("79EAC9C0-BAF9-11CE-8C82-00AA004BA90B");
//    public static Guid IID_IBindStatusCallBack = new Guid("79EAC9C1-BAF9-11CE-8C82-00AA004BA90B");
//    public static Guid IID_IOleObject = new Guid("00000112-0000-0000-C000-000000000046");
//    public static Guid IID_IOleWindow = new Guid("00000114-0000-0000-C000-000000000046");
//    public static Guid IID_IServiceProvider = new Guid("6d5140c1-7436-11ce-8034-00aa006009fa");
//    public static Guid IID_IWebBrowser = new Guid("EAB22AC1-30C1-11CF-A7EB-0000C05BAE0B");
//    public static Guid IID_IWebBrowser2 = new Guid("D30C1661-CDAF-11d0-8A3E-00C04FC9E26E");
//    public static Guid CLSID_WebBrowser = new Guid("8856F961-340A-11D0-A96B-00C04FD705A2");
//    public static Guid CLSID_CGI_IWebBrowser = new Guid("ED016940-BD5B-11CF-BA4E-00C04FD70816");
//    public static Guid CLSID_CGID_DocHostCommandHandler = new Guid("F38BC242-B950-11D1-8918-00C04FC2C836");
//    public static Guid CLSID_ShellUIHelper = new Guid("64AB4BB7-111E-11D1-8F79-00C04FC2FBE1");
//    public static Guid CLSID_SecurityManager = new Guid("7b8a2d94-0ac9-11d1-896c-00c04fb6bfc4");
//    public static Guid IID_IShellUIHelper = new Guid("729FE2F8-1EA8-11d1-8F85-00C04FC2FBE1");
//    public static Guid Guid_MSHTML = new Guid("DE4BA900-59CA-11CF-9592-444553540000");
//    public static Guid CLSID_InternetSecurityManager = new Guid("7b8a2d94-0ac9-11d1-896c-00c04fB6bfc4");
//    public static Guid IID_IInternetSecurityManager = new Guid("79EAC9EE-BAF9-11CE-8C82-00AA004BA90B");
//    public static Guid CLSID_InternetZoneManager = new Guid("7B8A2D95-0AC9-11D1-896C-00C04FB6BFC4");
//    public static Guid CGID_ShellDocView = new Guid("000214D1-0000-0000-C000-000000000046");
//    //SID_SDownloadManager same as IID
//    public static Guid SID_SDownloadManager = new Guid("988934A4-064B-11D3-BB80-00104B35E7F9");
//    public static Guid IID_IDownloadManager = new Guid("988934A4-064B-11D3-BB80-00104B35E7F9");
//    public static Guid IID_IHttpNegotiate = new Guid("79eac9d2-baf9-11ce-8c82-00aa004ba90b");
//    public static Guid IID_IStream = new Guid("0000000c-0000-0000-C000-000000000046");
//    public static Guid DIID_HTMLDocumentEvents2 = new Guid("3050f613-98b5-11cf-bb82-00aa00bdce0b");
//    public static Guid DIID_HTMLWindowEvents2 = new Guid("3050f625-98b5-11cf-bb82-00aa00bdce0b");
//    public static Guid DIID_HTMLElementEvents2 = new Guid("3050f60f-98b5-11cf-bb82-00aa00bdce0b");

//    public static Guid IID_IDataObject = new Guid("0000010e-0000-0000-C000-000000000046");

//    public static Guid CLSID_InternetShortcut = new Guid("FBF23B40-E3F0-101B-8488-00AA003E56F8");
//    public static Guid IID_IUniformResourceLocatorA = new Guid("FBF23B80-E3F0-101B-8488-00AA003E56F8");
//    public static Guid IID_IUniformResourceLocatorW = new Guid("CABB0DA0-DA57-11CF-9974-0020AFD79762");
//    public static Guid IID_IHTMLBodyElement = new Guid("3050F1D8-98B5-11CF-BB82-00AA00BDCE0B");

//    public static Guid CLSID_CUrlHistory = new Guid("3C374A40-BAE4-11CF-BF7D-00AA006946EE");

//    public static Guid CLSID_HTMLDocument = new Guid("25336920-03F9-11cf-8FD0-00AA00686F13");
//    public static Guid IID_IPropertyNotifySink = new Guid("9BFBBC02-EFF1-101A-84ED-00AA00341D07");

//    public static Guid IID_IProtectFocus = new Guid("D81F90A3-8156-44F7-AD28-5ABB87003274");

//    public static Guid IID_IHTMLOMWindowServices = new Guid("3050f5fc-98b5-11cf-bb82-00aa00bdce0b");

//    public const int NOERROR = 0;
//    public const int S_OK = 0;
//    public const int S_FALSE = 1;
//    public const int E_PENDING = unchecked((int)0x8000000A);
//    public const int E_HANDLE = unchecked((int)0x80070006);
//    public const int E_NOTIMPL = unchecked((int)0x80004001);
//    public const int E_NOINTERFACE = unchecked((int)0x80004002);
//    //ArgumentNullException. NullReferenceException uses COR_E_NULLREFERENCE
//    public const int E_POINTER = unchecked((int)0x80004003);
//    public const int E_ABORT = unchecked((int)0x80004004);
//    public const int E_FAIL = unchecked((int)0x80004005);
//    public const int E_OUTOFMEMORY = unchecked((int)0x8007000E);
//    public const int E_ACCESSDENIED = unchecked((int)0x80070005);
//    public const int E_UNEXPECTED = unchecked((int)0x8000FFFF);
//    public const int E_FLAGS = unchecked((int)0x1000);
//    public const int E_INVALIDARG = unchecked((int)0x80070057);

//    //Wininet
//    public const int ERROR_SUCCESS = 0;
//    public const int ERROR_FILE_NOT_FOUND = 2;
//    public const int ERROR_ACCESS_DENIED = 5;
//    public const int ERROR_INSUFFICIENT_BUFFER = 122;
//    public const int ERROR_NO_MORE_ITEMS = 259;
//}

//public sealed class WinApis
//{
//    public const uint MAX_PATH = 512;
//    public const uint STGM_READ = 0x00000000;
//    public const uint SHDVID_SSLSTATUS = 33;
//    public const int GWL_WNDPROC = -4;

//    public const short
//        //defined inWTypes.h
//        // 0 == FALSE, -1 == TRUE
//        //typedef short VARIANT_BOOL;
//        VAR_TRUE = -1,
//        VAR_FALSE = 0;

//    [DllImport("shell32.dll", CharSet = CharSet.Auto)]
//    public static extern IntPtr ExtractIcon(IntPtr hInst, string lpszExeFileName, int nIconIndex);

//    [DllImport("user32.dll")]
//    public static extern bool DestroyIcon(IntPtr hIcon);

//    [DllImport("user32", SetLastError = true, CharSet = CharSet.Auto)]
//    public static extern int CallWindowProc(
//        IntPtr lpPrevWndFunc, IntPtr hWnd, int Msg, int wParam, int lParam);

//    [DllImport("user32", SetLastError = true, CharSet = CharSet.Auto)]
//    public static extern IntPtr SetWindowLong(
//        IntPtr hWnd, int nIndex, IntPtr newProc);

//    [DllImport("ole32.dll", SetLastError = true,
//    ExactSpelling = true, CharSet = CharSet.Auto)]
//    public static extern int RevokeObjectParam(
//        [In, MarshalAs(UnmanagedType.LPWStr)] string pszKey);

//    //[DllImport("urlmon.dll", SetLastError = true)]
//    //public static extern int RegisterBindStatusCallback(
//    //    [MarshalAs(UnmanagedType.Interface)] IBindCtx pBc,
//    //    [MarshalAs(UnmanagedType.Interface)] DownloadManagerImpl.IBindStatusCallback pBSCb,
//    //    [Out, MarshalAs(UnmanagedType.Interface)] out IBindStatusCallback ppBSCBPrev,
//    //    [In, MarshalAs(UnmanagedType.U4)] UInt32 dwReserved); 

//    //[DllImport("user32.dll", SetLastError = true)]
//    //public static extern int GetClipboardFormatName(uint format, [Out] StringBuilder
//    //   lpszFormatName, int cchMaxCount);

//    [DllImport("user32.dll", SetLastError = true)]
//    public static extern IntPtr GetWindowDC(IntPtr hWnd);



//    [DllImport("gdi32.dll", SetLastError = true)]
//    public static extern IntPtr CreateCompatibleBitmap(IntPtr hdc, int nWidth,
//       int nHeight);

//    [DllImport("gdi32.dll", ExactSpelling = true, SetLastError = true)]
//    public static extern IntPtr CreateCompatibleDC(IntPtr hdc);

//    [DllImport("gdi32.dll", ExactSpelling = true, SetLastError = true)]
//    public static extern bool DeleteDC(IntPtr hdc);

//    [DllImport("gdi32.dll", ExactSpelling = true, SetLastError = true)]
//    public static extern IntPtr SelectObject(IntPtr hdc, IntPtr hgdiobj);

//    [DllImport("gdi32.dll", ExactSpelling = true, SetLastError = true)]
//    public static extern bool DeleteObject(IntPtr hObject);


//    [DllImport("ole32.dll", ExactSpelling = true, CharSet = CharSet.Auto)]
//    public static extern int CreateBindCtx(
//        [MarshalAs(UnmanagedType.U4)] uint dwReserved,
//        [Out, MarshalAs(UnmanagedType.Interface)] out IBindCtx ppbc);


//    [DllImport("urlmon.dll", ExactSpelling = true, CharSet = CharSet.Auto)]
//    public static extern int CreateURLMoniker(
//        [MarshalAs(UnmanagedType.Interface)] IMoniker pmkContext,
//        [MarshalAs(UnmanagedType.LPWStr)] string szURL,
//        [Out, MarshalAs(UnmanagedType.Interface)] out IMoniker ppmk);

//    public const uint URL_MK_LEGACY = 0;
//    public const uint URL_MK_UNIFORM = 1;
//    public const uint URL_MK_NO_CANONICALIZE = 2;
//    [DllImport("urlmon.dll", ExactSpelling = true, CharSet = CharSet.Auto)]
//    public static extern int CreateURLMonikerEx(
//        [MarshalAs(UnmanagedType.Interface)] IMoniker pmkContext,
//        [MarshalAs(UnmanagedType.LPWStr)] string szURL,
//        [Out, MarshalAs(UnmanagedType.Interface)] out IMoniker ppmk,
//        uint URL_MK_XXX); //Flags, one of 

//    [DllImport("user32.dll", CharSet = CharSet.Auto)]
//    public static extern IntPtr SendMessage(HandleRef hWnd, uint Msg,
//        IntPtr wParam, IntPtr lParam);

//    [DllImport("user32.dll", CharSet = CharSet.Auto)]
//    public static extern IntPtr SendMessage(HandleRef hWnd, uint Msg,
//        IntPtr wParam, ref StringBuilder lParam);



//    [DllImport("ole32.dll", CharSet = CharSet.Auto)]
//    public static extern int CreateStreamOnHGlobal(IntPtr hGlobal, bool fDeleteOnRelease,
//      [MarshalAs(UnmanagedType.Interface)] out IStream ppstm);

//    [DllImport("user32.dll")]
//    public static extern short GetKeyState(int nVirtKey);


//    //MessageBox(new IntPtr(0), "Text", "Caption", 0 );
//    [DllImport("user32.dll", CharSet = CharSet.Auto)]
//    public static extern uint MessageBox(
//        IntPtr hWnd, String text, String caption, uint type);


//    [DllImport("user32.dll")]
//    public static extern bool IsWindow(IntPtr hWnd);

//    [DllImport("user32.dll")]
//    public static extern bool IsWindowVisible(IntPtr hWnd);

//    [DllImport("user32.dll")]
//    public static extern bool BringWindowToTop(IntPtr hWnd);

//    [DllImport("user32.dll", SetLastError = true, CharSet = CharSet.Auto)]
//    public static extern IntPtr FindWindow(string lpClassName, string lpWindowName);

//    [DllImport("user32.dll")]
//    public static extern IntPtr GetWindow(IntPtr hWnd, uint uCmd);

//    [DllImport("user32.dll")]
//    public static extern int GetWindowText(IntPtr hWnd, StringBuilder title, int size);

//    [DllImport("user32.dll")]
//    public static extern uint RealGetWindowClass(IntPtr hWnd, StringBuilder pszType, uint cchType);

//    public static string GetWindowName(IntPtr Hwnd)
//    {
//        if (Hwnd == IntPtr.Zero)
//            return string.Empty;
//        // This function gets the name of a window from its handle
//        StringBuilder Title = new StringBuilder((int)WinApis.MAX_PATH);
//        WinApis.GetWindowText(Hwnd, Title, (int)WinApis.MAX_PATH);

//        return Title.ToString().Trim();
//    }

//    public static string GetWindowClass(IntPtr Hwnd)
//    {
//        if (Hwnd == IntPtr.Zero)
//            return string.Empty;
//        // This function gets the name of a window class from a window handle
//        StringBuilder Title = new StringBuilder((int)WinApis.MAX_PATH);
//        WinApis.RealGetWindowClass(Hwnd, Title, (int)WinApis.MAX_PATH);

//        return Title.ToString().Trim();
//    }

//    [DllImport("user32.dll")]
//    public static extern IntPtr SetFocus(IntPtr hWnd);



//    //[DllImport("user32.dll", SetLastError = true, CharSet = CharSet.Auto)]
//    //public static extern uint RegisterClipboardFormat(string lpszFormat);

//    [DllImport("ole32.dll")]
//    public static extern void ReleaseStgMedium(
//        [In, MarshalAs(UnmanagedType.Struct)]
//            ref System.Runtime.InteropServices.ComTypes.STGMEDIUM pmedium);

//    [DllImport("shell32.dll", CharSet = CharSet.Auto)]
//    public static extern uint DragQueryFile(IntPtr hDrop, uint iFile,
//       [Out] StringBuilder lpszFile, uint cch);

//    [DllImport("kernel32.dll")]
//    public static extern IntPtr GlobalLock(IntPtr hMem);

//    [DllImport("kernel32.dll")]
//    public static extern bool GlobalUnlock(IntPtr hMem);

//    [DllImport("kernel32.dll")]
//    public static extern UIntPtr GlobalSize(IntPtr hMem);

//    [DllImport("wininet.dll", SetLastError = true)]
//    public static extern long FindCloseUrlCache(IntPtr hEnumHandle);

//    [DllImport("wininet.dll", SetLastError = true)]
//    public static extern IntPtr FindFirstUrlCacheEntry(string lpszUrlSearchPattern, IntPtr lpFirstCacheEntryInfo, out UInt32 lpdwFirstCacheEntryInfoBufferSize);

//    [DllImport("wininet.dll", SetLastError = true)]
//    public static extern long FindNextUrlCacheEntry(IntPtr hEnumHandle, IntPtr lpNextCacheEntryInfo, out UInt32 lpdwNextCacheEntryInfoBufferSize);

//    [DllImport("wininet.dll", SetLastError = true)]
//    public static extern bool GetUrlCacheEntryInfo(string lpszUrlName, IntPtr lpCacheEntryInfo, out UInt32 lpdwCacheEntryInfoBufferSize);

//    [DllImport("wininet.dll", SetLastError = true)]
//    public static extern long DeleteUrlCacheEntry(string lpszUrlName);

//    [DllImport("wininet.dll", SetLastError = true)]
//    public static extern IntPtr RetrieveUrlCacheEntryStream(string lpszUrlName, IntPtr lpCacheEntryInfo, out UInt32 lpdwCacheEntryInfoBufferSize, long fRandomRead, UInt32 dwReserved);

//    [DllImport("wininet.dll", SetLastError = true)]
//    public static extern IntPtr ReadUrlCacheEntryStream(IntPtr hUrlCacheStream, UInt32 dwLocation, IntPtr lpBuffer, out UInt32 lpdwLen, UInt32 dwReserved);

//    [DllImport("wininet.dll", SetLastError = true)]
//    public static extern long UnlockUrlCacheEntryStream(IntPtr hUrlCacheStream, UInt32 dwReserved);




//    /// <summary>
//    /// UrlCache functionality is taken from:
//    /// Scott McMaster (smcmaste@hotmail.com)
//    /// CodeProject article
//    /// 
//    /// There were some issues with preparing URLs
//    /// for RegExp to work properly. This is
//    /// demonstrated in AllForms.SetupCookieCachePattern method
//    /// 
//    /// urlPattern:
//    /// . Dump the entire contents of the cache.
//    /// Cookie: Lists all cookies on the system.
//    /// Visited: Lists all of the history items.
//    /// Cookie:.*\.example\.com Lists cookies from the example.com domain.
//    /// http://www.example.com/example.html$: Lists the specific named file if present
//    /// \.example\.com: Lists any and all entries from *.example.com.
//    /// \.example\.com.*\.gif$: Lists the .gif files from *.example.com.
//    /// \.js$: Lists the .js files in the cache.
//    /// </summary>
//    /// <param name="urlPattern"></param>
//    /// <returns></returns>
//    public static ArrayList FindUrlCacheEntries(string urlPattern)
//    {
//        ArrayList results = new ArrayList();

//        IntPtr buffer = IntPtr.Zero;
//        UInt32 structSize;

//        //This call will fail but returns the size required in structSize
//        //to allocate necessary buffer
//        IntPtr hEnum = FindFirstUrlCacheEntry(null, buffer, out structSize);
//        try
//        {
//            if (hEnum == IntPtr.Zero)
//            {
//                int lastError = Marshal.GetLastWin32Error();
//                if (lastError == Constants.ERROR_INSUFFICIENT_BUFFER)
//                {
//                    //Allocate buffer
//                    buffer = Marshal.AllocHGlobal((int)structSize);
//                    //Call again, this time it should succeed
//                    hEnum = FindFirstUrlCacheEntry(urlPattern, buffer, out structSize);
//                }
//                else if (lastError == Constants.ERROR_NO_MORE_ITEMS)
//                {
//                    return results;
//                }
//            }

//            INTERNET_CACHE_ENTRY_INFO result = (INTERNET_CACHE_ENTRY_INFO)Marshal.PtrToStructure(buffer, typeof(INTERNET_CACHE_ENTRY_INFO));
//            try
//            {
//                if (Regex.IsMatch(result.lpszSourceUrlName, urlPattern, RegexOptions.IgnoreCase))
//                {
//                    results.Add(result);
//                }
//            }
//            catch (ArgumentException ae)
//            {
//                throw new ApplicationException("Invalid regular expression, details=" + ae.Message);
//            }

//            if (buffer != IntPtr.Zero)
//            {
//                try { Marshal.FreeHGlobal(buffer); }
//                catch { }
//                buffer = IntPtr.Zero;
//                structSize = 0;
//            }

//            //Loop through all entries, attempt to find matches
//            while (true)
//            {
//                long nextResult = FindNextUrlCacheEntry(hEnum, buffer, out structSize);
//                if (nextResult != 1) //TRUE
//                {
//                    int lastError = Marshal.GetLastWin32Error();
//                    if (lastError == Constants.ERROR_INSUFFICIENT_BUFFER)
//                    {
//                        buffer = Marshal.AllocHGlobal((int)structSize);
//                        nextResult = FindNextUrlCacheEntry(hEnum, buffer, out structSize);
//                    }
//                    else if (lastError == Constants.ERROR_NO_MORE_ITEMS)
//                    {
//                        break;
//                    }
//                }

//                result = (INTERNET_CACHE_ENTRY_INFO)Marshal.PtrToStructure(buffer, typeof(INTERNET_CACHE_ENTRY_INFO));
//                if (Regex.IsMatch(result.lpszSourceUrlName, urlPattern, RegexOptions.IgnoreCase))
//                {
//                    results.Add(result);
//                }

//                if (buffer != IntPtr.Zero)
//                {
//                    try { Marshal.FreeHGlobal(buffer); }
//                    catch { }
//                    buffer = IntPtr.Zero;
//                    structSize = 0;
//                }
//            }
//        }
//        finally
//        {
//            if (hEnum != IntPtr.Zero)
//            {
//                FindCloseUrlCache(hEnum);
//            }
//            if (buffer != IntPtr.Zero)
//            {
//                try { Marshal.FreeHGlobal(buffer); }
//                catch { }
//            }
//        }

//        return results;
//    }

//    /// <summary>
//    /// Attempts to delete a cookie or cache entry
//    /// </summary>
//    /// <param name="url">INTERNET_CACHE_ENTRY_INFO.lpszSourceUrlName</param>
//    public static void DeleteFromUrlCache(string url)
//    {
//        long apiResult = DeleteUrlCacheEntry(url);
//        if (apiResult != 0)
//        {
//            return;
//        }

//        int lastError = Marshal.GetLastWin32Error();
//        if (lastError == Constants.ERROR_ACCESS_DENIED)
//        {
//            throw new ApplicationException("Access denied: " + url);
//        }
//        else
//        {
//            throw new ApplicationException("Insufficient buffer: " + url);
//        }
//    }

//    [DllImport("user32.dll", SetLastError = true)]
//    public static extern bool SystemParametersInfo(uint uiAction, uint uiParam,
//        IntPtr pvParam, uint fWinIni);

//    private const uint SPIF_UPDATEINIFILE = 0x0001;
//    private const uint SPIF_SENDWININICHANGE = 0x0002;
//    //SPIF_SENDCHANGE       SPIF_SENDWININICHANGE
//    private const uint SPI_SETBEEP = 0x0002;

//    public static bool SetSystemBeep(bool bEnable)
//    {
//        if (bEnable)
//            return SystemParametersInfo(SPI_SETBEEP, 1, IntPtr.Zero, (SPIF_UPDATEINIFILE | SPIF_SENDWININICHANGE));
//        else
//            return SystemParametersInfo(SPI_SETBEEP, 0, IntPtr.Zero, (SPIF_UPDATEINIFILE | SPIF_SENDWININICHANGE));
//    }

//}

//[StructLayout(LayoutKind.Sequential)]
//public struct INTERNET_CACHE_ENTRY_INFO
//{
//    public UInt32 dwStructSize;
//    public string lpszSourceUrlName;
//    public string lpszLocalFileName;
//    public UInt32 CacheEntryType;
//    public UInt32 dwUseCount;
//    public UInt32 dwHitRate;
//    public UInt32 dwSizeLow;
//    public UInt32 dwSizeHigh;
//    public IntPtr lpHeaderInfo;
//    public UInt32 dwHeaderInfoSize;
//    public string lpszFileExtension;
//    public UInt32 dwExemptDelta;
//};

//[ComImport, ComVisible(true)]
//[Guid("00000114-0000-0000-C000-000000000046")]
//[InterfaceType(ComInterfaceType.InterfaceIsIUnknown)]
//public interface IOleWindow
//{
//    //IOleWindow
//    [return: MarshalAs(UnmanagedType.I4)]
//    [PreserveSig]
//    int GetWindow([In, Out] ref IntPtr phwnd);

//    [return: MarshalAs(UnmanagedType.I4)]
//    [PreserveSig]
//    int ContextSensitiveHelp([In, MarshalAs(UnmanagedType.Bool)] bool
//        fEnterMode);
//}

//public enum GetWindow_Cmd
//{
//    GW_HWNDFIRST = 0,
//    GW_HWNDLAST = 1,
//    GW_HWNDNEXT = 2,
//    GW_HWNDPREV = 3,
//    GW_OWNER = 4,
//    GW_CHILD = 5,
//    GW_ENABLEDPOPUP = 6
//}